题目大意:给一个含有 n(2≤n≤1000) 个点的无向图,图中每个顶点至少有 (n+1)/2 个相邻点,让求一条 Hamilton 回路
注意到 "每个顶点至少有 (n+1)/2 个相邻点" 这句话,满足 Ore 定理,直接构造解即可,构造的方法就是在证明定理 2 时使用的方法
#include <cstring>
#include <cstdio>
#include <iostream>
#include <list>
#include<stdio.h>
using namespace std;
struct Hamilton_Circuit {
static const int N=1006;
bool G[N][N], vs[N];
int n, next[N], head, tail;
void init(int _n) {
n=_n;
memset(G, 0, sizeof G);
}
void DFS_Head(int u) {
vs[u]=1;
for(int i=0; i<n; i++) if(G[i][u] && !vs[i]) {
next[i]=u;
DFS_Head(i);
return;
}
head=u;
}
void DFS_Tail(int u) {
vs[u]=1;
for(int i=0; i<n; i++) if(G[u][i] && !vs[i]) {
next[u]=i;
DFS_Tail(i);
return;
}
tail=u;
}
void Reverse(int u) {
for(int i=next[u], temp, last=-1; i!=-1; i=temp) {
temp=next[i];
next[i]=last;
last=i;
}
int temp=tail;
tail=next[u];
next[u]=temp;
}
int Find(int u) {
for(int i=head; i!=-1; i=next[i]) {
if(G[u][next[i]]) return i;
}
return -1;
}
bool Extend(int u) {
if(G[u][head]) {
next[u]=head;
return 1;
}
int pre=Find(u);
if(pre==-1) return 0;
next[u]=next[pre];
next[tail]=head;
next[tail=pre]=-1;
return 1;
}
void Solve() {
memset(next, -1, sizeof next);
memset(vs, 0, sizeof vs);
DFS_Head(0), DFS_Tail(0);
int Len=1;
for(int i=head; i!=tail; i=next[i], Len++);
for(int i; 1; ) {
if(!G[tail][head]) {
for(i=next[head]; !(G[i][tail] && G[next[i]][head]); i=next[i]);
Reverse(i);
}
if(Len==n) break;
for(i=0; i<n; i++) if(!vs[i] && Extend(i)) {
head=i, vs[i]=1, Len++;
break;
}
}
}
void PRINT() {
for(int i=head; head!=0; i=next[i]) {
next[tail]=head;
tail=head;
head=next[head];
next[tail]=-1;
}
for(int i=head; i!=-1; i=next[i]) {
printf("%d", i+1);
if(next[i]==-1) printf(" 1\n");
else printf(" ");
}
}
};
Hamilton_Circuit fuck;
int n;
int main() {
//scanf("%d", &n);
std::cin>>n;
fuck.init(n);
for(int i=0; i<n; i++) {
for(int x; ; ) {
//scanf("%d", &x);
std::cin>>x;
fuck.G[i][x-1]=1;
x=getchar();
if(x=='\n' || x=='\r' || x==EOF) break;
}
}
fuck.Solve();
fuck.PRINT();
return 0;
}